import requests
import time
import random
import hashlib
import xml.etree.ElementTree as ET

class WechatPayService:
    def __init__(self, config):
        self.config = config

    def unified_order(self, order):
        """调用微信支付统一下单接口"""
        nonce_str = self._generate_nonce_str()
        params = {
            'appid': self.config['appid'],
            'mch_id': self.config['mch_id'],
            'nonce_str': nonce_str,
            'body': f'订单 {order.order_number}',
            'out_trade_no': order.order_number,
            'total_fee': int(order.total_amount * 100),  # 单位：分
            'spbill_create_ip': '127.0.0.1',  # 实际项目中应获取客户端IP
            'notify_url': self.config['notify_url'],
            'trade_type': 'JSAPI',
            'openid': order.wechat_pay_openid
        }
        params['sign'] = self._generate_sign(params)
        xml_data = self._dict_to_xml(params)
        response = requests.post(self.config['unified_order_url'], data=xml_data.encode('utf-8'))
        result = self._xml_to_dict(response.text)
        if result.get('return_code') == 'SUCCESS' and result.get('result_code') == 'SUCCESS':
            prepay_id = result.get('prepay_id')
            pay_params = {
                'appId': self.config['appid'],
                'timeStamp': str(int(time.time())),
                'nonceStr': nonce_str,
                'package': f'prepay_id={prepay_id}',
                'signType': 'MD5'
            }
            pay_params['paySign'] = self._generate_sign(pay_params)
            return pay_params
        else:
            raise Exception(result.get('return_msg', '微信支付统一下单失败'))

    def _generate_nonce_str(self):
        """生成随机字符串"""
        return ''.join(random.sample('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 32))

    def _generate_sign(self, params):
        """生成签名"""
        sorted_params = sorted(params.items(), key=lambda x: x[0])
        sign_str = '&'.join([f'{k}={v}' for k, v in sorted_params if k != 'sign'])
        sign_str += f'&key={self.config["key"]}'
        sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
        return sign

    def _dict_to_xml(self, params):
        """字典转XML"""
        xml = '<xml>'
        for k, v in params.items():
            xml += f'<{k}>{v}</{k}>'
        xml += '</xml>'
        return xml

    def _xml_to_dict(self, xml_data):
        """XML转字典"""
        root = ET.fromstring(xml_data)
        result = {}
        for child in root:
            result[child.tag] = child.text
        return result